﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Amazon.SimpleEmail;
using Amazon.SimpleEmail.Model;
using System.IO;

namespace SES_Server
{
    public class SendStatistics
    {
        public int totalBounces;
        public int totalComplaints;
        public int totalDeliveryAttempts;
        public int totalRejects;

        public double Max24HourSend;
        public double MaxSendRate;
        public double SentLast24Hours;
    }
    public class AmazonSES
    {
        //Amazon AWS Identifiers
        public static string awsAccessKey { get; set; }
        public static string awsSecretKey { get; set; }

        public AmazonSES(string AWSAcesskey, string AWSSecretKey)
        {
            awsAccessKey = AWSAcesskey;
            awsSecretKey = AWSSecretKey;

            ses = new AmazonSimpleEmailServiceClient(awsAccessKey, awsSecretKey);
        }

        private AmazonSimpleEmailServiceClient ses { get; set; }

        //Add, Delete and request list of Verfified Emails
        public List<string> GetVerifiedEmails()
        {
            try
            {
                List<string> verified = ses.ListVerifiedEmailAddresses(new ListVerifiedEmailAddressesRequest()).ListVerifiedEmailAddressesResult.VerifiedEmailAddresses;
                return verified;
            }
            catch (Exception ex)
            {
                new ErrorLogger().WriteErrorLog(ex);
                return new List<string>();
            }
        }
        public Tuple<bool, string> DeleteVerifiedEmail(string email)
        {
            DeleteVerifiedEmailAddressRequest deleteVerifiedRequest = new DeleteVerifiedEmailAddressRequest();
            deleteVerifiedRequest.EmailAddress = email;
            try
            {
                ses.DeleteVerifiedEmailAddress(deleteVerifiedRequest);
                return new Tuple<bool, string>(true, "");
            }
            catch (Exception ex)
            {
                new ErrorLogger().WriteErrorLog(ex);
                return new Tuple<bool, string>(false, ex.Message);
            }
        }
        public Tuple<bool, string> VerifyEmail(string email)
        {
            VerifyEmailAddressRequest emailVerificationRequest = new VerifyEmailAddressRequest();
            emailVerificationRequest.EmailAddress = email;
            try
            {
                ses.VerifyEmailAddress(emailVerificationRequest);
                return new Tuple<bool, string>(true, "To complete the verification process, please click the confirmation link sent to your inbox");
            }
            catch (Exception ex)
            {
                new ErrorLogger().WriteErrorLog(ex);
                return new Tuple<bool, string>(false, "Failed to verify email!");
            }
        }

        //Send Emails
        public Tuple<bool, string> SendRawEmail(string from, byte[] data)
        {
            SendRawEmailRequest rawEmailRequest = new SendRawEmailRequest();
            RawMessage rawMessage = new RawMessage();
            rawMessage.Data = new MemoryStream();
            rawMessage.Data.Write(data, 0, data.Length);

            rawEmailRequest.RawMessage = rawMessage;
            try
            {
                ses.SendRawEmail(rawEmailRequest);
                return new Tuple<bool, string>(true, "Email Sucessfully Sent!");
            }
            catch (Exception ex)
            {
                new ErrorLogger().WriteErrorLog(ex);
                return new Tuple<bool, string>(false, "Email Failed to Send! - " + ex.Message);
            }
        }
        public Tuple<bool, string> SendEmail(string email_from, string[] email_to, string[] email_bcc, string[] email_cc, string subject, string body)
        {
            Message msg = new Message();
            msg.Subject = new Content(subject);
            msg.Body = new Body(new Content(body));

            Destination dest = new Destination();
            if (email_bcc.Length == 0) dest.ToAddresses.AddRange(email_to);
            if (email_bcc.Length == 0) dest.BccAddresses.AddRange(email_bcc);
            if (email_bcc.Length == 0) dest.CcAddresses.AddRange(email_cc);

            SendEmailRequest sendEmailRequest = new SendEmailRequest();
            sendEmailRequest.ReplyToAddresses.Add(email_from); //maybe add more
            sendEmailRequest.Source = email_from;
            sendEmailRequest.ReturnPath = email_from; //Undeliverable messages get sent do this address
            sendEmailRequest.Message = msg;
            sendEmailRequest.Destination = dest;

            try
            {
                ses.SendEmail(sendEmailRequest);
                return new Tuple<bool, string>(true, "Email Sucessfully Sent!");
            }
            catch (Exception ex)
            {
                new ErrorLogger().WriteErrorLog(ex);
                return new Tuple<bool, string>(false, "Email Failed to Send! - "+ ex.Message);
            }

        }

        //Get current send statistics
        public SendStatistics GetCurrentStatistics()
        {
            try
            {
                GetSendQuotaResponse sendQuotaResponse = ses.GetSendQuota(new GetSendQuotaRequest());
                GetSendQuotaResult sendQuotaResult = sendQuotaResponse.GetSendQuotaResult;
                GetSendStatisticsResponse sendStatisticsResponse = ses.GetSendStatistics(new GetSendStatisticsRequest());
                List<SendDataPoint> dataPoints = sendStatisticsResponse.GetSendStatisticsResult.SendDataPoints;

                /*
                 * Each Datapoint contain statistics on sending data for a 15 minute period of activity. 
                 */

                SendStatistics st = new SendStatistics();
                st.totalBounces = (int)dataPoints.Select(s => s.Bounces).Sum();
                st.totalComplaints = (int)dataPoints.Select(s => s.Complaints).Sum();
                st.totalDeliveryAttempts = (int)dataPoints.Select(s => s.DeliveryAttempts).Sum();
                st.totalRejects = (int)dataPoints.Select(s => s.Rejects).Sum();
                st.Max24HourSend = sendQuotaResult.Max24HourSend;
                st.MaxSendRate = sendQuotaResult.MaxSendRate;
                st.SentLast24Hours = sendQuotaResult.SentLast24Hours;

                var timePeriods = dataPoints.OrderBy(s => s.Timestamp).Select(s => s.Timestamp);
                return st;
            }
            catch
            {
                return new SendStatistics();
            }
        }
    }
}
